﻿/*
 * This file is part of MonoStrategy.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://monostrategy.codeplex.com/
 */

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using MonoStrategy.RenderSystem;
using System.Xml;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.IO;

namespace MonoStrategy
{
    [ObfuscationAttribute(Feature = "renaming", ApplyToMembers = true)]
    public class Button : Control
    {
        private Control[] m_StateCtrls = new Control[6];

        [XmlAttribute]
        public Boolean IsDown { get; set; }
        [XmlAttribute]
        public Boolean IsToggleable { get; set; }
        [XmlAttribute]
        public String ImageTemplate { get; set; }

        public event DNotifyHandler<Button> OnClick;

        public Button()
            : base()
        {
            IsToggleable = true;
        }

        public override void XMLPostProcess(XMLGUILayout inLayout)
        {
            base.XMLPostProcess(inLayout);

            if (!String.IsNullOrEmpty(ImageTemplate))
            {
                if (Children.Count > 0)
                    throw new ArgumentException("A button with an image template shall not have any children.");

                // check resources paths
                String[] states = new String[]{
                    "Up", "Over", "Down", "DownOver", "Disabled", "DisabledDown",
                    "NormalState", "OverState", "DownState", "DownOverState", "NormalDisabledState", "DownDisabledState",
                };

                for (int i = 0; i < 6; i++)
                {
                    String fileName = ImageTemplate + states[i] + ".png";

                    if (Program.GUIConfig.Exists(fileName))
                    {
                        var img = new Image()
                        {
                            SourceString = fileName,
                            Width = this.Width,
                            Height = this.Height,
                            Id = states[i + 6],
                        };

                        img.XMLPostProcess(inLayout);

                        Children.Add(img);
                    }
                }
            }

            foreach (var state in Children)
            {
                switch (state.Id)
                {
                    case "NormalState": if (m_StateCtrls[0] != null) throw new ArgumentException(); m_StateCtrls[0] = state; break;
                    case "OverState": if (m_StateCtrls[1] != null) throw new ArgumentException(); m_StateCtrls[1] = state; break;
                    case "DownState": if (m_StateCtrls[2] != null) throw new ArgumentException(); m_StateCtrls[2] = state; break;
                    case "DownOverState": if (m_StateCtrls[3] != null) throw new ArgumentException(); m_StateCtrls[3] = state; break;
                    case "NormalDisabledState": if (m_StateCtrls[4] != null) throw new ArgumentException(); m_StateCtrls[4] = state; break;
                    case "DownDisabledState": if (m_StateCtrls[5] != null) throw new ArgumentException(); m_StateCtrls[5] = state; break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            if (m_StateCtrls[0] == null)
                throw new ArgumentException("A button needs at least state definitions for NormalState.");

            if (m_StateCtrls[2] == null)
                m_StateCtrls[2] = m_StateCtrls[0];
        }


        protected virtual void DoClick(Boolean inIsSynthetic) 
        {
            if (IsToggleable)
                IsDown = !IsDown;

            if (OnClick != null)
                OnClick(this);
        }

        protected override void DoMouseButtonUp(int inMouseX, int inMouseY, int inButton) 
        {
            if (inButton == LeftMouseButton)
                DoClick(false);
        }

        protected override void Render(int inChainLeft, int inChainTop)
        {
            foreach (var state in m_StateCtrls)
            {
                if (state == null)
                    continue;

                state.IsVisible = false;
            }

            if (!IsDown && IsEnabled && !IsMouseOver) // NormalState
            {
                m_StateCtrls[0].IsVisible = true;
            }
            else if (!IsDown && IsEnabled && IsMouseOver && !IsMouseDown) // OverState
            {
                if (m_StateCtrls[1] == null)
                    m_StateCtrls[0].IsVisible = true;
                else
                    m_StateCtrls[1].IsVisible = true;
            }
            else if ((IsDown || IsMouseDown) && IsEnabled) // DownState
            {
                m_StateCtrls[2].IsVisible = true;
            }
            else if (IsDown && IsEnabled && IsMouseOver) // DownOver
            {
                if (m_StateCtrls[3] == null)
                    m_StateCtrls[2].IsVisible = true;
                else
                    m_StateCtrls[3].IsVisible = true;
            }
            else if (!IsDown && !IsEnabled) // NormalDisabledState
            {
                if (m_StateCtrls[4] == null)
                    m_StateCtrls[0].IsVisible = true;
                else
                    m_StateCtrls[4].IsVisible = true;
            }
            else if (IsDown && !IsEnabled) // DownDisabledState
            {
                if (m_StateCtrls[5] == null)
                    m_StateCtrls[0].IsVisible = true;
                else
                    m_StateCtrls[5].IsVisible = true;
            }
            else
                m_StateCtrls[0].IsVisible = true;

            base.Render(inChainLeft, inChainTop);
        }
    }
}
